import { Environment, OrbitControls } from '@react-three/drei';
import { Canvas, useThree } from '@react-three/fiber';
import { Suspense, useEffect, useRef, useState } from 'react';
import { Vector3, Camera, Group } from 'three';
import { Box } from './Box';
import { TexturedBox } from './TexturedBox';
import { GLBModel } from './GLBModel';
import { ZoomIn, ZoomOut, RotateCcw } from 'lucide-react';
import React from 'react';
import Confetti from 'react-confetti';

// 常量定义
const ANIMATION_DURATION = 2000;
const INITIAL_CAMERA_POSITION = new Vector3(10, 12, 35);
const TARGET_POSITION = new Vector3(-1, 1, 0);
const START_POSITION = new Vector3(-4, 0, 0);
const END_POSITION = new Vector3(2, 0, 0);

// 类型定义
interface ModelAttributes {
  name: string;
  realLength: number;
  realWidth: number;
  realHeight: number;
}

interface BoxComparisonProps {
  itemDimensions: [number, number, number];
  containerDimensions: [number, number, number];
  showAnimation: boolean;
  fits: boolean | null;
  onAnimationComplete: () => void;
  itemTextureUrl?: string;
  containerTextureUrl?: string;
  itemModelUrl?: string;
  containerModelUrl?: string;
  onReset: () => void;
  onModelLoad?: (dimensions: Vector3) => void;
  onCustomAttributesLoad?: (attributes: ModelAttributes) => void;
  onCheck: () => void;
  error?: string;
}

interface AnimatedGroupProps {
  children: React.ReactNode;
  isAnimating: boolean;
  fits: boolean | null;
  itemDimensions: [number, number, number];
}

// 材质属性类型
interface MaterialProps {
  color: string;
  emissive: string;
  emissiveIntensity: number;
  metalness: number;
  roughness: number;
  opacity: number;
  renderOrder: number;
  depthWrite: boolean;
  depthTest: boolean;
}

// 场景组件
function Scene({ cameraRef }: { cameraRef: React.MutableRefObject<Camera | null> }) {
  const { camera } = useThree();

  useEffect(() => {
    if (cameraRef) {
      cameraRef.current = camera;
    }
  }, [camera, cameraRef]);

  return null;
}

// 动画组件
const AnimatedGroup = React.forwardRef<Group, AnimatedGroupProps>(
  ({ children, isAnimating, fits, itemDimensions }, ref) => {
    const groupRef = useRef<Group>(null);
    const startTime = useRef(Date.now());
    const initialScale = useRef<Vector3 | null>(null);
    const animationFrameRef = useRef<number>();

    // 将内部ref与外部ref同步
    useEffect(() => {
      if (ref && 'current' in ref) {
        ref.current = groupRef.current;
      }
    }, [ref]);

    // 保存初始缩放比例
    useEffect(() => {
      if (groupRef.current) {
        initialScale.current = groupRef.current.scale.clone();
      }

      return () => {
        if (animationFrameRef.current) {
          cancelAnimationFrame(animationFrameRef.current);
        }
      };
    }, []); // 只在组件挂载时执行一次

    useEffect(() => {
      if (!isAnimating || !groupRef.current) return;

      const animate = () => {
        const now = Date.now();
        const elapsed = now - startTime.current;
        const progress = Math.min(elapsed / ANIMATION_DURATION, 1);

        // 使用缓动函数
        const easeProgress = progress < 0.5
          ? 2 * progress * progress
          : 1 - Math.pow(-2 * progress + 2, 2) / 2;

        // 根据fits决定最终位置
        const endPos = fits ? END_POSITION : new Vector3(2, 0, 0);
        const currentPos = new Vector3().lerpVectors(START_POSITION, endPos, easeProgress);
        
        // 设置物品位置，y轴位置为物品高度的一半
        if (groupRef.current) {
          groupRef.current.position.copy(currentPos);
          groupRef.current.position.y = itemDimensions[1] / 2;

          // 确保保持原始缩放比例
          if (initialScale.current) {
            groupRef.current.scale.copy(initialScale.current);
          }
        }

        if (progress < 1) {
          animationFrameRef.current = requestAnimationFrame(animate);
        }
      };

      startTime.current = Date.now();
      animationFrameRef.current = requestAnimationFrame(animate);

      return () => {
        if (animationFrameRef.current) {
          cancelAnimationFrame(animationFrameRef.current);
        }
      };
    }, [isAnimating, fits]); // 只监听动画状态和适配状态的变化

    return (
      <group ref={groupRef} position={[-4, itemDimensions[1] / 2, 0]}>
        {children}
      </group>
    );
  }
);

AnimatedGroup.displayName = 'AnimatedGroup';

// 获取材质属性
function getMaterialProps(
  hasTexture: boolean,
  baseColor: string,
  emissiveColor: string,
  opacity: number,
  renderOrder: number
): MaterialProps {
  return {
    color: hasTexture ? "#808080" : baseColor,
    emissive: hasTexture ? "#404040" : emissiveColor,
    emissiveIntensity: hasTexture ? 0.1 : 0.5,
    metalness: hasTexture ? 0.4 : 0.7,
    roughness: hasTexture ? 0.4 : 0.2,
    opacity,
    renderOrder,
    depthWrite: renderOrder === 2,
    depthTest: true
  };
}

export function BoxComparison({ 
  itemDimensions, 
  containerDimensions, 
  showAnimation,
  fits,
  onAnimationComplete,
  containerTextureUrl,
  itemModelUrl,
  containerModelUrl,
  onReset,
  onModelLoad,
  onCustomAttributesLoad,
  onCheck,
  error
}: BoxComparisonProps) {
  const [isAnimating, setIsAnimating] = useState(false);
  const [hasShownResult, setHasShownResult] = useState(false);
  const [showConfetti, setShowConfetti] = useState(false);
  const cameraRef = useRef<Camera | null>(null);
  const groupRef = useRef<Group | null>(null);

  // 重置函数
  const resetState = () => {
    setIsAnimating(false);
    setHasShownResult(false);
    setShowConfetti(false);

    // 重置物品位置到初始位置
    if (groupRef.current) {
      groupRef.current.position.copy(START_POSITION);
      groupRef.current.position.y = itemDimensions[1] / 2;
    }

    // 重置相机视角
    if (cameraRef.current) {
      cameraRef.current.position.copy(INITIAL_CAMERA_POSITION);
      cameraRef.current.lookAt(TARGET_POSITION);
    }
  };

  // 监听模型URL变化
  useEffect(() => {
    resetState();
  }, [itemModelUrl]);

  // 相机控制
  const handleZoomIn = () => {
    if (cameraRef.current && cameraRef.current.position.length() > 5) {
      cameraRef.current.position.multiplyScalar(0.8);
    }
  };

  const handleZoomOut = () => {
    if (cameraRef.current && cameraRef.current.position.length() < 5000) {
      cameraRef.current.position.multiplyScalar(1.2);
    }
  };

  const handleResetView = () => {
    if (cameraRef.current) {
      cameraRef.current.position.copy(INITIAL_CAMERA_POSITION);
      cameraRef.current.lookAt(TARGET_POSITION);
    }
  };

  const handleReset = () => {
    resetState();
    // 调用父组件的重置函数
    onReset();
  };

  // 动画控制
  useEffect(() => {
    if (!showAnimation) {
      setIsAnimating(false);
      setHasShownResult(false);
      setShowConfetti(false);
      return;
    }

    if (fits !== null && !hasShownResult) {
      setIsAnimating(true);
      setShowConfetti(true);
      const animationTimer = setTimeout(() => {
        setIsAnimating(false);
        setHasShownResult(true);
        onAnimationComplete();

        setTimeout(() => {
          setShowConfetti(false);
        }, 2000); // 烟花效果在动画结束后1秒消失
      }, ANIMATION_DURATION);

      return () => {
        clearTimeout(animationTimer);
      };
    }
  }, [showAnimation, fits, onAnimationComplete, hasShownResult]);

  const containerProps = {
    position: [2, containerDimensions[1]/2, 0] as [number, number, number],
    dimensions: containerDimensions,
    ...getMaterialProps(!!containerTextureUrl, "#f87171", "#ef4444", 0.3, 2)
  };

  return (
    <div className="relative w-full h-full">
      {/* 控制按钮 */}
      <div className="absolute top-4 right-4 z-10 flex flex-col md:flex-row gap-2">
        <button
          onClick={onCheck}
          className="px-4 py-2.5 bg-white/90 hover:bg-white/100 text-gray-700 rounded-xl shadow-lg backdrop-blur-sm
            transition-all duration-200 flex items-center justify-center gap-2 text-base font-medium
            focus:outline-none focus:ring-2 focus:ring-gray-400 min-w-[120px]
            disabled:opacity-50 disabled:cursor-not-allowed"
          disabled={!itemModelUrl}
        >
          开始验证
        </button>
        <button
          onClick={handleReset}
          className="px-4 py-2.5 bg-white/90 hover:bg-white/100 text-gray-700 rounded-xl shadow-lg backdrop-blur-sm
            transition-all duration-200 flex items-center justify-center gap-2 text-base font-medium
            focus:outline-none focus:ring-2 focus:ring-gray-400 min-w-[120px]
            disabled:opacity-50 disabled:cursor-not-allowed"
          disabled={!itemModelUrl}
        >
          <RotateCcw size={18} strokeWidth={1.5} />
          重新验证
        </button>
      </div>
      
      {/* 结果显示 */}
      {((showAnimation && fits !== null && hasShownResult) || error) && (
        <div className="absolute top-20 md:top-4 left-1/2 -translate-x-1/2 z-10">
          <div className="flex flex-col items-center gap-2">
            {showAnimation && fits !== null && hasShownResult && (
              <div className={`py-3.5 px-8 text-center rounded-xl font-medium min-w-[180px] text-base
                ${fits ? "bg-green-50 text-green-700" : "bg-rose-50/80 text-rose-600"}
                animate-fade-in shadow-lg backdrop-blur-sm border
                ${fits ? "border-green-200" : "border-rose-200"}
                flex items-center justify-center gap-3`}
              >
                <img 
                  src={fits ? "/imgs/success.png" : "/imgs/failed.png"} 
                  alt={fits ? "成功" : "失败"}
                  className={`w-8 h-8 object-contain transition-all duration-500
                    ${fits ? "animate-bounce-custom" : "animate-shake-custom"}
                  `}
                />
                {fits ? "可以装下！" : "装不下！"}
              </div>
            )}
            {error && (
              <div className="py-3.5 px-8 bg-red-50 text-red-700 text-base rounded-xl shadow-lg backdrop-blur-sm border border-red-200 min-w-[180px] text-center">
                {error}
              </div>
            )}
          </div>
        </div>
      )}
      
      {/* 相机控制 */}
      <div className="absolute bottom-4 right-4 flex flex-col gap-2.5 z-10">
        <button
          onClick={handleZoomIn}
          className="p-3 bg-white/90 hover:bg-white/100 text-gray-700 rounded-xl shadow-lg backdrop-blur-sm
            transition-all duration-200 flex items-center justify-center
            focus:outline-none focus:ring-2 focus:ring-gray-400"
          title="放大"
        >
          <ZoomIn size={20} strokeWidth={1.5} />
        </button>
        <button
          onClick={handleZoomOut}
          className="p-3 bg-white/90 hover:bg-white/100 text-gray-700 rounded-xl shadow-lg backdrop-blur-sm
            transition-all duration-200 flex items-center justify-center
            focus:outline-none focus:ring-2 focus:ring-gray-400"
          title="缩小"
        >
          <ZoomOut size={20} strokeWidth={1.5} />
        </button>
        <button
          onClick={handleResetView}
          className="p-3 bg-white/90 hover:bg-white/100 text-gray-700 rounded-xl shadow-lg backdrop-blur-sm
            transition-all duration-200 flex items-center justify-center
            focus:outline-none focus:ring-2 focus:ring-gray-400"
          title="重置视角"
        >
          <RotateCcw size={20} strokeWidth={1.5} />
        </button>
      </div>

      {/* 3D场景 */}
      <div className="w-full h-full bg-gradient-to-b from-slate-950 via-slate-900 to-slate-800 rounded-lg overflow-hidden shadow-2xl">
        <Canvas 
          camera={{ position: [6, 8, 20], fov: 60 }}
          shadows
        >
          <Scene cameraRef={cameraRef} />
          <Environment 
            files="/env/sunset.hdr"
            background={false}
            blur={0.8}
          />
          <ambientLight intensity={0.5} /> {/* 增加环境光强度 */}
          <pointLight position={[10, 10, 10]} intensity={0.8} color="#ffffff" />
          <pointLight position={[-10, -10, -10]} intensity={0.3} color="#ffffff" />
          <spotLight
            position={[0, 5, 0]}
            angle={0.3}
            penumbra={1}
            intensity={0.8}
            castShadow
          />
          
          {/* 地面 */}
          <mesh rotation={[-Math.PI / 2, 0, 0]} position={[0, 0, 0]} receiveShadow>
            <planeGeometry args={[50, 50]} />
            <meshStandardMaterial color="#1a1a1a" />
          </mesh>
          
          {/* 物品 */}
          <Suspense fallback={null}>
            <AnimatedGroup 
              ref={groupRef}
              isAnimating={isAnimating} 
              fits={fits}
              itemDimensions={itemDimensions}
            >
              {itemModelUrl && (
                <GLBModel
                  url={itemModelUrl}
                  dimensions={itemDimensions}
                  position={[0, 0, 0]}
                  opacity={0.8}
                  renderOrder={1}
                  onLoad={onModelLoad}
                  onCustomAttributesLoad={onCustomAttributesLoad}
                />
              )}
            </AnimatedGroup>
          </Suspense>
          
          {/* 容器 */}
          <Suspense fallback={null}>
            {containerModelUrl ? (
              <GLBModel
                url={containerModelUrl}
                dimensions={containerDimensions}
                position={[2, containerDimensions[1]/2, 0]}
                opacity={0.6}
                renderOrder={1}
              />
            ) : containerTextureUrl ? (
              <TexturedBox {...containerProps} textureUrl={containerTextureUrl} />
            ) : (
              <Box {...containerProps} />
            )}
          </Suspense>

          <OrbitControls 
            makeDefault
            target={[-1, 1, 0]}
            enableDamping
            dampingFactor={0.05}
            autoRotate={false}
            enableZoom={true}
            enablePan={true}
            minDistance={8}
            maxDistance={50}
            enableRotate={true}
            rotateSpeed={0.5}
            zoomSpeed={0.5}
            panSpeed={0.5}
            maxPolarAngle={Math.PI / 2}
            minPolarAngle={0}
            maxAzimuthAngle={Infinity}
            minAzimuthAngle={-Infinity}
          />
          <gridHelper args={[50, 50]} position={[0, 0, 0]} />
        </Canvas>
      </div>

      {/* 添加动画关键帧 */}
      <style>
        {`
          .animate-bounce-custom {
            animation: bounce 1.2s ease-in-out;
          }
          .animate-shake-custom {
            animation: shake 1.2s ease-in-out;
          }
          @keyframes shake {
            0%, 100% { transform: translateX(0) rotate(0deg); }
            20% { transform: translateX(-8px) rotate(-3deg); }
            40% { transform: translateX(8px) rotate(3deg); }
            60% { transform: translateX(-8px) rotate(-2deg); }
            80% { transform: translateX(8px) rotate(2deg); }
          }
          @keyframes bounce {
            0%, 100% { transform: translateY(0) scale(1); }
            50% { transform: translateY(-10px) scale(1.1); }
          }
        `}
      </style>

      {showConfetti && fits && <Confetti width={window.innerWidth} height={window.innerHeight} />}
    </div>
  );
}